package co.fitstart.entity.user;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Transient;

import org.hibernate.annotations.DynamicUpdate;

import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.JsonIdentityReference;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;

import co.fitstart.entity.course.Course;
import co.fitstart.entity.order.Order;
import co.fitstart.entity.utils.DateFormatUtils;
import co.fitstart.entity.utils.StringUtils;

/**
 * 
 * @author mohanlan
 *
 */
@Entity
@Table(name = "student")
@DynamicUpdate
@JsonIgnoreProperties(value={"hibernate_lazy_initializer","handler","fieldHandler"})
public class Student {
    
    @Id
    @GeneratedValue
    private Long id;
    
    /** 创建时间 */
    private Date createTime;
    
    /** 真实姓名 */
    private String name;
    
    /** 学员编号 */
    private String code;
    
    /** 手机号码 */
    private String mobile;
    
    /** 头像 */
    private String avatar;
    
    /** 是否为线上学员*/
    private boolean online;
    
    /** 是否为线下学员*/
    private boolean offline;
    
    /** 学员标签 */
    private String tagIds;
    
    /** 线下课程优惠码 */
    private String offlineCode;
    
    /** 课程报名统计 */
    @Embedded
    @AttributeOverrides({
        @AttributeOverride(name = "onlineCount", column = @Column(name = "online_count")),
        @AttributeOverride(name = "individualCount", column = @Column(name = "individual_count")),
        @AttributeOverride(name = "groupCount", column = @Column(name = "group_count")),
        @AttributeOverride(name = "yearCount", column = @Column(name = "year_count"))
    })
    private StudentCourseStat stat;
    
    /** 最后购买课程  */
    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    @JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id")
    @JsonIdentityReference(alwaysAsId=true)
    private Course course;
    
    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    @JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id")
    @JsonIdentityReference(alwaysAsId=true)
    private User user;
    
    /** 是否导出学员档案 */
    private boolean exportArchives;
    
    @Column(name = "is_disabled")
    private boolean disabled;
    
    /**
     * The default constructor
     */
    public Student() {
        
    }

    /**
     * 
     * @param user
     * @param course
     */
    public Student(User user, Course course) {
        
        this.createTime = new Date();
        this.name = user.getName();
        
        this.code = DateFormatUtils.format(this.createTime, "yyyyMMdd") + 
                    String.format("%02d", Double.valueOf(Math.floor(Math.random() * 100)).intValue()) + 
                    user.getId().toString();
        
        this.mobile = user.getMobile();
        this.avatar = user.getProfile() == null ? null : user.getProfile().getAvatar();
        this.course = course;
        this.user = user;
        this.online = course.isOnline();
        this.offline = !course.isOnline();
        
        this.stat = new StudentCourseStat();
        
        this.exportArchives = false;
        
    }
    
    /**
     * 
     * @param user
     * @return
     */
    public boolean matches(User user) {
        return this.id.equals(user.getId());
    }
    
    /**
     * 
     * @param course
     * @return
     */
    public Student edit(Course course) {
        
        this.course = course;
        
        if(course.isOnline()) {
            this.online = true;
        } else {
            this.offline = true;
        }
        
        return this;
    }
    
    /**
     * 
     * @param order
     * @return
     */
    public Student increaseStat(Order order) {
        
        if(this.stat == null) {
            this.stat = new StudentCourseStat();
        }
        
        if(order.getOrderType().isOnline()) {
            this.stat.addOnlineCount(1);
        }else if(order.getOrderType().isIndividual()) {
            this.stat.addIndividualCount(1);
        }else if(order.getOrderType().isGroup()) {
            this.stat.addGroupCount(1);
        }else if(order.getOrderType().isYear()) {
            this.stat.addYearCount(1);
        }
        
        return this;
    }
    
    /**
     * 
     * @param fitnessTag
     * @return
     */
    public Student editTag(String tagIds) {
        this.tagIds = tagIds;
        return this;
    }
    
    /**
     * 
     * @return
     */
    public Student editOfflineCode() {
        this.offlineCode = String.valueOf(System.identityHashCode(this));
        return this;
    }
    
    /**
     * 
     * @return
     */
    @Transient
    public List<Long> getArrayTagIds() {
        List<Long> arrayTagIds = new ArrayList<>();
        if(tagIds != null) {
            for(String tagId : StringUtils.split(tagIds, ",")) {
                arrayTagIds.add(Long.parseLong(tagId));
            }
        }
        return arrayTagIds;
    }
    
    /**
     * 
     * @return
     */
    public Map<String, Object> describe() {
        Map<String, Object> parameters = new HashMap<String, Object>();
        parameters.put("discount", 0);
        parameters.put("discountCode", offlineCode);
        return parameters;
    }
    
    /**
     * 
     * @param name
     * @return
     */
    public Student editName(String name) {
        this.name = name;
        return this;
    }
    
    /**
     * 
     * @param mobile
     * @return
     */
    public Student editMobile(String mobile) {
        this.mobile = mobile;
        return this;
    }
    
    /**
     * 
     * @return
     */
    public Student exportArchives() {
        this.exportArchives = true;
        return this;
    }

    /**
     * @return the id
     */
    public Long getId() {
        return id;
    }

    /**
     * @return the createTime
     */
    public Date getCreateTime() {
        return createTime;
    }

    /**
     * @return the name
     */
    public String getName() {
        return name;
    }

    /**
     * @return the code
     */
    public String getCode() {
        return code;
    }

    /**
     * @return the mobile
     */
    public String getMobile() {
        return mobile;
    }

    /**
     * @return the avatar
     */
    public String getAvatar() {
        return avatar;
    }

    /**
     * @return the online
     */
    public boolean isOnline() {
        return online;
    }

    /**
     * @return the offline
     */
    public boolean isOffline() {
        return offline;
    }

    /**
     * @return the tagIds
     */
    public String getTagIds() {
        return tagIds;
    }

    /**
     * @return the offlineCode
     */
    public String getOfflineCode() {
        return offlineCode;
    }

    /**
     * @return the stat
     */
    public StudentCourseStat getStat() {
        return stat;
    }

    /**
     * @return the course
     */
    public Course getCourse() {
        return course;
    }

    /**
     * @return the user
     */
    public User getUser() {
        return user;
    }

    /**
     * @return the exportArchives
     */
    public boolean isExportArchives() {
        return exportArchives;
    }

    /**
     * @return the disabled
     */
    public boolean isDisabled() {
        return disabled;
    }

    /**
     * @param id the id to set
     */
    public void setId(Long id) {
        this.id = id;
    }

    /**
     * @param createTime the createTime to set
     */
    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }

    /**
     * @param name the name to set
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * @param code the code to set
     */
    public void setCode(String code) {
        this.code = code;
    }

    /**
     * @param mobile the mobile to set
     */
    public void setMobile(String mobile) {
        this.mobile = mobile;
    }

    /**
     * @param avatar the avatar to set
     */
    public void setAvatar(String avatar) {
        this.avatar = avatar;
    }

    /**
     * @param online the online to set
     */
    public void setOnline(boolean online) {
        this.online = online;
    }

    /**
     * @param offline the offline to set
     */
    public void setOffline(boolean offline) {
        this.offline = offline;
    }

    /**
     * @param tagIds the tagIds to set
     */
    public void setTagIds(String tagIds) {
        this.tagIds = tagIds;
    }

    /**
     * @param offlineCode the offlineCode to set
     */
    public void setOfflineCode(String offlineCode) {
        this.offlineCode = offlineCode;
    }

    /**
     * @param stat the stat to set
     */
    public void setStat(StudentCourseStat stat) {
        this.stat = stat;
    }

    /**
     * @param course the course to set
     */
    public void setCourse(Course course) {
        this.course = course;
    }

    /**
     * @param user the user to set
     */
    public void setUser(User user) {
        this.user = user;
    }

    /**
     * @param exportArchives the exportArchives to set
     */
    public void setExportArchives(boolean exportArchives) {
        this.exportArchives = exportArchives;
    }

    /**
     * @param disabled the disabled to set
     */
    public void setDisabled(boolean disabled) {
        this.disabled = disabled;
    }
}
